package com.lynn.common.dialog

import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.SparseArray
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import androidx.activity.ComponentDialog
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.FloatRange
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.annotation.StyleRes

fun BaseDialog.Builder.getScreenWidth(context: Context): Int {
    return context.resources.displayMetrics.widthPixels
}

fun BaseDialog.Builder.dp2px(context: Context, dpValue: Float): Float {
    return dpValue * context.resources.displayMetrics.density + 0.5f
}

/**
 * @description: 自定义Dialog，为了保持代码的整洁和可维护性。（要求不高的话可以使用原生自带的对话框）
 *   需要做的工作：
 *      1、外观主题
 *      2、显示和消失动画
 *      3、显示位置
 *      .......
 * @author: bailing
 * @datetime: 2025/5/29 09:38
 **/
class BaseDialog(context: Context, private val params: DialogParams) :
    ComponentDialog(context, R.style.Dialog_CustomTheme) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(params.mDialogView)
        if (params.mWidth == WindowManager.LayoutParams.WRAP_CONTENT) {
            params.mWidth = params.mDialogView.layoutParams.width
        }
        if (params.mHeight == WindowManager.LayoutParams.WRAP_CONTENT) {
            params.mHeight = params.mDialogView.layoutParams.height
        }
        window?.let { w ->
            val layoutParams = w.attributes
            // Kotlin 中的apply函数是一个扩展函数，主要用于对象的初始化和配置。
            layoutParams.apply {
                width = params.mWidth
                if (width > 0) {
                    width -= (params.mGap * 2)
                }
                height = params.mHeight
                gravity = params.mGravity
                if (params.mAnimationStyle != -1) {
                    windowAnimations = params.mAnimationStyle
                }
                if (params.mDimEnabled) {
                    w.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
                    dimAmount = params.mDimAmount
                } else {
                    w.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
                }
            }

            w.attributes = layoutParams
        }

        setCanceledOnTouchOutside(params.mCanceledOnTouchOutside) //点击外部区域是否取消
        setCancelable(params.mCancelable) //按返回键是否取消

        params.mOnShowListener?.let {
            setOnShowListener(it)
        }

        params.mOnDismissListener?.let {
            setOnDismissListener(it)
        }
    }

    abstract class Builder(val context: Context, @LayoutRes layoutResId: Int) {
        private var mParams: DialogParams = DialogParams()
        private var mDialog: BaseDialog? = null
        private var mActivity: Activity? = null

        /**
         * by  lazy ：是一种属性委托机制，用于实现属性的延迟初始化
         * 当第一次访问该属性时，by lazy会执行提供的Lambda表达式并缓存结果，
         *   后续访问直接返回缓存的值，从而优化性能，特别是在初始化成本较高的场景下。
         */
        val mDialogView: View by lazy {
            LayoutInflater.from(context).inflate(layoutResId, FrameLayout(context), false)
        }

        val mViewHolder: ViewHolder by lazy {
            ViewHolder.Companion.create(mDialogView)
        }

        init {
            mParams.mDialogView = mDialogView
            mActivity = getActivity(context)
        }

        protected fun getActivity(context: Context): Activity? {
            if (context is Activity) {
                return context
            }
            return null
        }

        /**
         * 是否显示背景暗淡度
         */
        protected fun setDimEnable(enable: Boolean): Builder {
            mParams.mDimEnabled = enable
            return this
        }

        /**
         * 设置背景暗淡度
         */
        protected fun setDimAmount(@FloatRange(from = 0.0, to = 1.0) dimAmount: Float): Builder {
            mParams.mDimAmount = dimAmount
            return this
        }

        /**
         * 设置显示位置
         */
        protected fun setGravity(gravity: Int): Builder {
            mParams.mGravity = gravity
            return this
        }

        /**
         * 设置宽高
         */
        protected fun setWidth(width: Int): Builder {
            mParams.mWidth = width
            return this
        }

        protected fun setHeight(height: Int): Builder {
            mParams.mHeight = height
            return this
        }

        /**
         * 设置左右空白
         */
        protected fun setHorizontalGap(gap: Int): Builder {
            mParams.mGap = gap
            return this
        }

        /**
         * 动画
         */
        protected fun setAnimationStyle(@StyleRes animationStyle: Int): Builder {
            mParams.mAnimationStyle = animationStyle
            return this
        }

        /**
         * 点击外部区域是否隐藏
         */
        protected fun setCanceledOnTouchOutside(cancel: Boolean): Builder {
            mParams.mCanceledOnTouchOutside = cancel
            return this
        }

        /**
         * 点击返回按钮是否隐藏
         */
        protected fun setCancelable(cancelable: Boolean): Builder {
            mParams.mCancelable = cancelable
            return this
        }

        /**
         * 设置显示监听
         */
        protected fun setOnShowListener(onShowListener: DialogInterface.OnShowListener): Builder {
            mParams.mOnShowListener = onShowListener
            return this
        }

        /**
         * 设置隐藏监听
         */
        protected fun setOnDismissListener(onDismissListener: DialogInterface.OnDismissListener): Builder {
            mParams.mOnDismissListener = onDismissListener
            return this
        }

        // 创建Dialog
        fun build(): BaseDialog {
            mDialog = BaseDialog(context, mParams)
            convertView(mViewHolder, mDialog!!)
            return mDialog!!
        }

        // Dialog是否被创建
        private fun isCreated(): Boolean {
            return mDialog != null
        }

        // Dialog是否显示
        private fun isShowing(): Boolean {
            if (mDialog != null && mDialog!!.isShowing) {
                return true
            }
            return false
        }

        abstract fun convertView(viewHolder: ViewHolder, dialog: BaseDialog)

        // 显示Dialog
        open fun show() {
            if (mActivity == null || mActivity!!.isFinishing || mActivity!!.isDestroyed) {
                return
            }
            if (!isCreated()) {
                build()
            }
            if (isShowing()) {
                return
            }
            mDialog!!.show()
        }

        // 隐藏Dialog
        fun dismiss() {
            if (mActivity == null || mActivity!!.isFinishing || mActivity!!.isDestroyed) {
                return
            }
            if (mDialog == null) {
                return
            }
            mDialog!!.dismiss()
        }
    }
}


/**
 * @description:  设置对话框所需的参数
 * @author: bailing
 * @datetime: 2025/5/29 10:52
 **/
class DialogParams {
    lateinit var mDialogView: View

    @FloatRange(from = 0.0, to = 1.0)
    var mDimAmount = 0.6F // 背景暗淡度
    var mDimEnabled = true // 是否显示背景暗淡度
    var mGravity = Gravity.CENTER //显示位置
    var mWidth: Int = ViewGroup.LayoutParams.WRAP_CONTENT // 宽度
    var mHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT // 高度
    var mGap: Int = 0 // 左右间隙
    var mCancelable: Boolean = true // 点击返回键是否隐藏
    var mCanceledOnTouchOutside: Boolean = true // 点击外部区域是否隐藏

    @StyleRes
    var mAnimationStyle: Int = -1

    var mOnShowListener: DialogInterface.OnShowListener? = null
    var mOnDismissListener: DialogInterface.OnDismissListener? = null
}

/**
 * @description: 对话框视图控件处理类
 * @author: bailing
 * @datetime: 2025/5/29 10:48
 **/
class ViewHolder(private val convertView: View) {

    companion object {
        fun create(view: View): ViewHolder {
            return ViewHolder(view)
        }
    }

    /**
     * Sparserray是Android中特有的数据结构,它有几个重要的特点：
     *
     * 1.以键值对形式进行存储，基于分查找,因此查找的时间复杂度为O(LogN);
     * 2.由于SparseArray中Key存储的是数组形式,因此可以直接以int作为Key。
     *  避免了HashMap的装箱拆箱操作,性能更高且int的存储开销远远小于Integer;
     * 3.采用了延迟删除的机制(针对数组的删除扩容开销大的问题的优化， 具体稍后分析) ;
     */
    private val views = SparseArray<View>()

    /**
     * 获取控件
     */
    fun <T : View> getView(@IdRes viewId: Int): T {
        var view = views.get(viewId)
        if (view == null) {
            view = convertView.findViewById(viewId)
            views.put(viewId, view)
        }
        return view as T
    }

    /**
     * 设置文本
     */
    fun setText(@IdRes viewId: Int, text: String) {
        val textView = getView<TextView>(viewId)
        textView.text = text
    }

    /**
     * 设置文本颜色
     */
    fun setTextColor(@IdRes viewId: Int, @ColorInt color: Int) {
        val textView = getView<TextView>(viewId)
        textView.setTextColor(color)
    }

    /**
     * 设置控件的背景图片
     */
    fun setBackgroundResource(@IdRes viewId: Int, @DrawableRes resId: Int) {
        val view = getView<View>(viewId)
        view.setBackgroundResource(resId)
    }

    /**
     * 设置控件的背景颜色
     */
    fun setBackgroundColor(@IdRes viewId: Int, @ColorInt color: Int) {
        val view = getView<View>(viewId)
        view.setBackgroundColor(color)
    }

    /**
     * 设置点击事件
     */
    fun setOnClickListener(@IdRes viewId: Int, listener: View.OnClickListener) {
        val view = getView<View>(viewId)
        view.setOnClickListener(listener)
    }
}
